package com.github.glomadrian.roadrunner;

import com.github.glomadrian.roadrunner.painter.configuration.PathPainterConfiguration;
import com.github.glomadrian.roadrunner.painter.configuration.factory.PathPainterConfigurationFactory;
import com.github.glomadrian.roadrunner.painter.indeterminate.IndeterminatePainter;
import com.github.glomadrian.roadrunner.painter.indeterminate.IndeterminatePathPainter;
import com.github.glomadrian.roadrunner.painter.indeterminate.factory.IndeterminatePainterFactory;
import com.github.glomadrian.roadrunner.path.PathContainer;
import com.github.glomadrian.roadrunner.utils.AssertUtils;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.app.Context;

import java.text.ParseException;

/**
 * @author Adrián García Lomas
 */
public class IndeterminateRoadRunner extends RoadRunner implements Component.DrawTask {
    private static final String TAG = "IndeterminateLoading";
    private int originalWidth;
    private int originalHeight;
    private String pathData;
    private PathContainer pathContainer;
    private IndeterminatePathPainter pathPainter;
    private IndeterminatePainter pathIndeterminatePainterSelected = IndeterminatePainter.MATERIAL;
    private PathPainterConfiguration pathPainterConfiguration;
    private boolean animateOnStart = true;
    private int tag;

    /**
     * IndeterminateRoadRunner
     *
     * @param context
     */
    public IndeterminateRoadRunner(Context context) {
        super(context);
        throw new UnsupportedOperationException("The view can not be created programmatically yet");
    }

    /**
     * IndeterminateRoadRunner
     *
     * @param context
     * @param attrs
     */
    public IndeterminateRoadRunner(Context context, AttrSet attrs) {
        super(context, attrs);
        System.out.println("IndeterminateRoadRunner");
        initPath(attrs);
        initConfiguration(attrs);
        invalidate();
    }

    /**
     * IndeterminateRoadRunner
     *
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    public IndeterminateRoadRunner(Context context, AttrSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPath(attrs);
        initConfiguration(attrs);
    }

    /**
     * setColor
     *
     * @param color
     */
    @Override
    public void setColor(int color) {
        pathPainter.setColor(color);
    }

    private void initPath(AttrSet attrs) {
        int animationValue = attrs.getAttr("path_animation_type").get().getIntegerValue();
        pathIndeterminatePainterSelected = IndeterminatePainter.fromId(animationValue);
        pathData = attrs.getAttr("path_data").get().getStringValue();
        originalWidth = attrs.getAttr("path_original_width").get().getIntegerValue();
        originalHeight = attrs.getAttr("path_original_height").get().getIntegerValue();
        animateOnStart = attrs.getAttr("roadRunner_animate_on_start").get().getBoolValue();

        AssertUtils.assertThis(pathData != null, "Path data must be defined", this.getClass());
        AssertUtils.assertThis(!pathData.isEmpty(), "Path data must be defined", this.getClass());
        AssertUtils.assertThis(!pathData.equals(""), "Path data must be defined", this.getClass());
        AssertUtils.assertThis(originalWidth > 0, "Original with of the path must be defined",
            this.getClass());
        AssertUtils.assertThis(originalHeight > 0, "Original height of the path must be defined",
            this.getClass());
    }

    private void initConfiguration(AttrSet attrs) {
        System.out.println("pathIndeterminatePainterSelected-" + pathIndeterminatePainterSelected);
        pathPainterConfiguration =
            PathPainterConfigurationFactory.makeConfiguration(attrs,
                pathIndeterminatePainterSelected);
    }

    private void initPathPainter() {
        pathPainter =
            IndeterminatePainterFactory.makeIndeterminatePathPainter(
                pathIndeterminatePainterSelected, pathContainer,
                this, pathPainterConfiguration);
    }

    /**
     * onSizeChanged
     *
     * @param w
     * @param h
     */
    protected void onSizeChanged(int w, int h) {
        try{
            pathContainer = buildPathData(w, h, pathData, originalWidth, originalHeight);
            initPathPainter();
        } catch (ParseException e) {
            System.out.println("Path parse exception:" + e);
        }
        if (animateOnStart) {
            start();
        }
    }

    /**
     * invalidate
     */
    @Override
    public void invalidate() {
        super.invalidate();
        this.addDrawTask(this::onDraw);
    }

    /** onDraw Tell the pathPainter to draw the path in the onDraw
     *
     * @param component
     * @param canvas
     */
    @Override
    public void onDraw(Component component, Canvas canvas) {
        tag ++;
        if (tag == 1) {
            onSizeChanged(this.getWidth(), this.getHeight());
        }
        pathPainter.paintPath(canvas);
    }

    /**
     * start
     */
    public void start() {
        pathPainter.start();
    }

    /**
     * stop
     */
    public void stop() {
        pathPainter.stop();
    }

    /**
     * restart
     */
    public void restart() {
        pathPainter.restart();
    }
}
